package com.bingxue.edu.management.education.service;

import com.bingxue.edu.common.enums.ClassCategoryEnum;
import com.bingxue.edu.common.enums.JoinTypeEnum;
import com.bingxue.edu.common.enums.StudentClassEnum;
import com.bingxue.edu.framework.mybatis.base.BaseService;
import com.bingxue.edu.framework.mybatis.query.QueryBuilder;
import com.bingxue.edu.management.education.model.entity.LessonStudent;
import com.bingxue.edu.management.education.model.query.LessonStudentQuery;
import com.bingxue.edu.management.education.model.resp.LessonStudentDetailResp;
import com.bingxue.edu.management.report.model.resp.LessonSignInStat;
import com.bingxue.edu.management.system.mapper.LessonStudentMapper;
import com.mybatisflex.core.query.QueryMethods;
import com.mybatisflex.core.query.QueryWrapper;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Service;

import java.util.List;
import java.util.Set;

import static com.bingxue.edu.management.education.model.entity.table.ClassInfoTableDef.CLASS_INFO;
import static com.bingxue.edu.management.education.model.entity.table.LessonStudentTableDef.LESSON_STUDENT;
import static com.bingxue.edu.management.education.model.entity.table.LessonTableDef.LESSON;
import static com.mybatisflex.core.query.QueryMethods.case_;
import static com.mybatisflex.core.query.QueryMethods.ifNull;
import static com.mybatisflex.core.query.QueryMethods.number;
import static com.mybatisflex.core.query.QueryMethods.sum;

/**
 * 课次业务类
 *
 * @author zq
 * @since 2024/08/26
 */
@Slf4j
@Service
@RequiredArgsConstructor
public class LessonStudentService extends BaseService<LessonStudentMapper, LessonStudent> {

    /**
     * 是否存在某个科目的长期班课消
     * 规则：学生不存在同科目的长期班课消记录
     */
    public boolean existLessonSignInRecord(String studentId, String subject) {
        return this.queryChain()
                .leftJoin(CLASS_INFO).on(CLASS_INFO.ID.eq(LESSON_STUDENT.LESSON_CLASS_ID))
                .where(LESSON_STUDENT.STUDENT_ID.eq(studentId))
                    .and(LESSON_STUDENT.STUDENT_CLASS_STATUS.eq(StudentClassEnum.NORMAL))
                    .and(LESSON_STUDENT.SIGN_IN_STATUS.eq(true))
                    .and(CLASS_INFO.CLASS_CATEGORY.eq(ClassCategoryEnum.LONG_TERM_CLASS))
                    .and(CLASS_INFO.SUBJECT.eq(subject))
                .exists();
    }

    /**
     * 查询最后一节已课消的课次记录
     */
    public LessonStudent getLastLessonByEnrollmentId(String enrollmentId) {
        return this.queryChain()
                .leftJoin(LESSON).on(LESSON.ID.eq(LESSON_STUDENT.LESSON_ID))
                .where(LESSON_STUDENT.ENROLLMENT_ID.eq(enrollmentId))
                    .and(LESSON_STUDENT.STUDENT_CLASS_STATUS.eq(StudentClassEnum.NORMAL))
                    .and(LESSON_STUDENT.SIGN_IN_STATUS.eq(true))
                .orderBy(LESSON.LESSON_INDEX.desc())
                .limit(1)
                .one();
    }

    /**
     * 根据报名id获取课次列表
     *
     * @param enrollmentId     报名id
     * @param onlyRemainLesson 是否仅包含剩余课次
     */
    public List<LessonStudent> getListByEnrollmentId(String enrollmentId, boolean onlyRemainLesson) {
        return this.queryChain()
                .select(LESSON_STUDENT.ALL_COLUMNS, LESSON.LESSON_INDEX)
                .from(LESSON_STUDENT)
                .leftJoin(LESSON).on(LESSON_STUDENT.LESSON_ID.eq(LESSON.ID))
                .where(LESSON_STUDENT.ENROLLMENT_ID.eq(enrollmentId))
                    .and(LESSON_STUDENT.STUDENT_CLASS_STATUS.eq(StudentClassEnum.NORMAL))
                    .and(LESSON_STUDENT.SIGN_IN_STATUS.eq(false).when(onlyRemainLesson))
//                    .and(LESSON.LESSON_STATUS.ne(LessonStatusEnum.COMPLETED).when(onlyRemainLesson))
                .list();
    }

    public List<LessonStudentDetailResp> getLessonStudentList(LessonStudentQuery query) {
        QueryWrapper queryWrapper = QueryBuilder.build(query)
                .orderBy(LESSON_STUDENT.STUDENT_JOIN_TYPE.asc())
                .orderBy(LESSON_STUDENT.SIGN_IN_STATUS.desc());
        return this.getMapper().selectListWithRelationsByQueryAs(queryWrapper, LessonStudentDetailResp.class);
    }
    /**
     * 根据课次顺序获取学生课次列表
     *
     * @param enrollmentId    报名id
     * @param lessonIndexList 课次顺序列表
     */
    public List<LessonStudent> getListByLessonIndex(String enrollmentId, List<Integer> lessonIndexList) {
        return this.queryChain()
                .select(LESSON_STUDENT.ALL_COLUMNS, LESSON.LESSON_INDEX)
                .from(LESSON_STUDENT)
                .leftJoin(LESSON).on(LESSON_STUDENT.LESSON_ID.eq(LESSON.ID))
                .where(LESSON_STUDENT.ENROLLMENT_ID.eq(enrollmentId))
                    .and(LESSON_STUDENT.STUDENT_CLASS_STATUS.eq(StudentClassEnum.NORMAL))
                    .and(LESSON.LESSON_INDEX.in(lessonIndexList))
                .list();
    }

    /**
     * 查询课次
     *
     * @param enrollmentId    报名id
     * @param lessonIndex     课次顺序
     */
    public LessonStudent getOneByLessonIndex(String enrollmentId, Integer lessonIndex, StudentClassEnum status) {
        return this.queryChain()
                .select(LESSON_STUDENT.ALL_COLUMNS, LESSON.LESSON_INDEX)
                .from(LESSON_STUDENT)
                .leftJoin(LESSON).on(LESSON_STUDENT.LESSON_ID.eq(LESSON.ID))
                .where(LESSON_STUDENT.ENROLLMENT_ID.eq(enrollmentId))
                    .and(LESSON_STUDENT.STUDENT_CLASS_STATUS.eq(status))
                    .and(LESSON.LESSON_INDEX.eq(lessonIndex))
                .one();
    }

    /**
     * 更新学生课次状态
     *
     * @param lessonStudentList 学生课次列表
     * @param status            状态
     */
    public void updateStudentClassStatus(List<LessonStudent> lessonStudentList, StudentClassEnum status) {
        List<String> ids = lessonStudentList.stream().map(LessonStudent::getId).toList();
        this.updateChain()
                .set(LESSON_STUDENT.STUDENT_CLASS_STATUS, status)
                .where(LESSON_STUDENT.ID.in(ids))
                .update();
    }

    public LessonStudent initLessonStudent(String studentId, String classId, String id, JoinTypeEnum joinType) {
        LessonStudent lessonStudent = new LessonStudent();
        lessonStudent.setEnrollmentId(id);
        lessonStudent.setLessonClassId(classId);
        lessonStudent.setStudentClassId(classId);
        lessonStudent.setStudentId(studentId);
        lessonStudent.setStudentClassStatus(StudentClassEnum.NORMAL);
        lessonStudent.setSignInStatus(false);
        lessonStudent.setStudentJoinType(joinType);
        return lessonStudent;
    }

    public List<LessonSignInStat> getLessonSignInStat(Set<String> lessonIdList) {
        return this.queryChain()
                .select(LESSON_STUDENT.LESSON_ID,
                        ifNull(QueryMethods.count(), number(0)).as(LessonSignInStat::getTotalCount),
                        sum(case_(LESSON_STUDENT.SIGN_IN_STATUS).when(1).then(1).else_(0).end()).as(LessonSignInStat::getSignInCount))
                .from(LESSON_STUDENT)
                .where(LESSON_STUDENT.LESSON_ID.in(lessonIdList))
                .and(LESSON_STUDENT.STUDENT_CLASS_STATUS.eq(StudentClassEnum.NORMAL))
                .groupBy(LESSON_STUDENT.LESSON_ID)
                .listAs(LessonSignInStat.class);
    }

}
